package com.yami.shop.security.api.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.model.User;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PrincipalUtil;
import com.yami.shop.dao.UserMapper;
import com.yami.shop.security.api.util.WeChatUtil;
import com.yami.shop.security.common.bo.UserInfoInTokenBO;
import com.yami.shop.security.common.dto.AuthenticationDTO;
import com.yami.shop.security.common.enums.SysTypeEnum;
import com.yami.shop.security.common.manager.PasswordCheckManager;
import com.yami.shop.security.common.manager.PasswordManager;
import com.yami.shop.security.common.manager.TokenStore;
import com.yami.shop.security.common.vo.TokenInfoVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jodd.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * @author 菠萝凤梨
 * @date 2022/3/28 15:20
 */
@RestController
@Tag(name = "登录")
public class LoginController {
    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PasswordCheckManager passwordCheckManager;

    @Autowired
    private PasswordManager passwordManager;

    @PostMapping("/login")
    @Operation(summary = "账号密码(用于前端登录)" , description = "通过账号/手机号/用户名密码登录，还要携带用户的类型，也就是用户所在的系统")
    public ServerResponseEntity<TokenInfoVO> login(
            @Valid @RequestBody AuthenticationDTO authenticationDTO) {
        String mobileOrUserName = authenticationDTO.getUserName();
        User user = getUser(mobileOrUserName);

        String decryptPassword = passwordManager.decryptPassword(authenticationDTO.getPassWord());

        // 半小时内密码输入错误十次，已限制登录30分钟
        passwordCheckManager.checkPassword(SysTypeEnum.ORDINARY,authenticationDTO.getUserName(), decryptPassword, user.getLoginPassword());

        UserInfoInTokenBO userInfoInToken = new UserInfoInTokenBO();
        userInfoInToken.setUserId(user.getUserId());
        userInfoInToken.setSysType(SysTypeEnum.ORDINARY.value());
        userInfoInToken.setEnabled(user.getStatus() == 1);
        // 存储token返回vo
        TokenInfoVO tokenInfoVO = tokenStore.storeAndGetVo(userInfoInToken);
        return ServerResponseEntity.success(tokenInfoVO);
    }

    @PostMapping("/wxlogin")
    @Operation(summary = "微信用户信息获取" , description = "微信用户信息获取")
    public ServerResponseEntity<JSONObject> wxLogin(@Valid @RequestBody AuthenticationDTO authenticationDTO) throws Exception{
        return ServerResponseEntity.success(getSession(authenticationDTO));
    }

    @PostMapping("/wxphone")
    @Operation(summary = "微信手机号获取" , description = "微信手机号获取")
    public ServerResponseEntity<TokenInfoVO> wxPhone(@Valid @RequestBody JSONObject params) throws Exception{
        // 获取手机号吗
        String phone=getPhone(params);
        if(StringUtil.isBlank(phone)){
            throw new YamiShopBindException("手机号码解密失败");
        }
        // 通过openid修改手机号码
        User user=userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getOpenid, params.getStr("openid")));
        if(user==null){
            throw new YamiShopBindException("登录异常");
        }
        user.setUserMobile(phone);
        userMapper.updateById(user);

        UserInfoInTokenBO userInfoInToken = new UserInfoInTokenBO();
        userInfoInToken.setUserId(user.getUserId());
        userInfoInToken.setSysType(SysTypeEnum.ORDINARY.value());
        userInfoInToken.setEnabled(user.getStatus() == 1);
        // 存储token返回vo
        TokenInfoVO tokenInfoVO = tokenStore.storeAndGetVo(userInfoInToken);
        tokenInfoVO.setPhone(phone);
        return ServerResponseEntity.success(tokenInfoVO);
    }

    @PostMapping("/wxupdate")
    @Operation(summary = "微信信息存储" , description = "微信信息存储")
    public ServerResponseEntity<Boolean> wxUpdate(@Valid @RequestBody JSONObject params) throws Exception{
        // 通过openid修改手机号码
        User user=userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getOpenid, params.getStr("openid")));
        if(user==null){
            throw new YamiShopBindException("登录异常");
        }
        user.setNickName(params.getStr("nickName"));
        user.setPic(params.getStr("avatarUrl"));
        userMapper.updateById(user);
        return ServerResponseEntity.success(true);
    }

    private User getUser(String mobileOrUserName) {
        User user = null;
        // 手机验证码登陆，或传过来的账号很像手机号
        if (PrincipalUtil.isMobile(mobileOrUserName)) {
            user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUserMobile, mobileOrUserName));
        }
        // 如果不是手机验证码登陆， 找不到手机号就找用户名
        if  (user == null) {
            user = userMapper.selectOneByUserName(mobileOrUserName);
        }
        if (user == null) {
            throw new YamiShopBindException("账号或密码不正确");
        }
        return user;
    }

    private String getPhone(JSONObject params) throws Exception {
        JSONObject userInfo=WeChatUtil.getUserInfo(params.getStr("encrypteData"),params.getStr("session_key"),params.getStr("iv"));
        return userInfo.getStr("phoneNumber");
    }

    private JSONObject getSession(AuthenticationDTO authenticationDTO) {
        JSONObject sessionInfo=WeChatUtil.getSessionKeyOrOpenId("wx1b6121ee3f32dbcf","687062fc24d2ee19f6daa51d835a7b84",authenticationDTO.getCodeid());
        User user=userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getOpenid, sessionInfo.getStr("openid")));
        if(user==null){
            String userId = IdUtil.simpleUUID();
            Date now = new Date();
            //创建用户
            user=new User();
            user.setUserId(userId);
            user.setOpenid(sessionInfo.getStr("openid"));
            user.setNickName(authenticationDTO.getUserName());
            user.setPic(authenticationDTO.getPic());
            user.setModifyTime(now);
            user.setUserRegtime(now);
            user.setStatus(1);
            userMapper.insert(user);
        }else if(user.getStatus().intValue()==0){
            throw new YamiShopBindException("账号已被禁");
        }
        return sessionInfo;
    }
}
